/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		auto common.cpp
 * PURPOSE:		automatic (C++ semantics) containers common support
 *				
 */

#define _NEW_

//address placement new
void *operator new(size_t size, void *p)
{
    return p;
}

//matching delete for address placement new
void operator delete(void *pos1, void *pos2)
{}

//default allocator for POD (no constructor/destructor/assignment operator) data
template <class T> struct default_pod_allocator
{
	typedef default_pod_allocator<T> type;

	T *alloc(size_t length)
	{
		return c_cast<T *>(operator new(length)); //treat as opaque blob
	}
	void free(T *x)
	{
		delete c_cast<void *>(x); //treat as opaque blob
	}
};

template <class T> struct default_allocator
{
	typedef default_allocator<T> type;

	T *alloc(size_t length)
	{
		T *buff = c_cast<T *>(new char[length]);
		buff = new(buff) T;
		return buff;
	}
	void free(T *x)
	{
		delete x;
	}
};

template <class T> struct array_allocator
{
	typedef array_allocator<T> type;

	T *alloc(size_t length)
	{
		if(length % sizeof(T))
			return 0;
		else
			return new T[length / sizeof(T)];
	}
	void free(T *x)
	{
		delete[] x;
	}
};

template <class T> struct Win32_LocalHeap_pod_allocator
{
	typedef Win32_LocalHeap_pod_allocator<T> type;

	T *alloc(size_t length)
	{
		return static_cast<T *>(LocalAlloc(LMEM_FIXED, length));
	}
	void free(T *x)
	{
		LocalFree(static_cast<void *>(x));
	}
};

template <class T> struct auto_take //for special constructor, takes ownership of x (as opposed to making a copy)
{
	T *ptr;
	explicit auto_take(T *x) :
		ptr(x)
	{}
	template <class U> operator auto_take<U>() const
	{
		return auto_take<U>(ptr);
	}
};

template <class T> FORCEINLINE auto_take<T> auto_take_(T *ptr)
{
	return auto_take<T>(ptr);
}